package com.iot08.common.utils;

import com.iot08.common.constant.Const;
import com.iot08.common.constant.ConstVideo;
import com.iot08.common.entity.app.StartEndTime;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @version 1.0
 * @Description: 日期相关处理工具
 * @time: 2020/10/12 9:36
 * @author: Rock
 */
public class DateUtil {

    public static final String FORMAT_1 = "yyyy-MM-dd HH:mm:ss";

    public static final String FORMAT_2 = "yyyyMMddHHmmss";

    public static final String FORMAT_3 = "yyyy-MM-dd-HHmmss";

    public static final String FORMAT_4 = "yyyy-MM-dd";

    public static final String FORMAT_5 = "yyyyMMdd";

    public static final String FORMAT_6 = "yyMMddHHmmss";

    public static final String FORMAT_7 = "yyyy-MM-dd HH:mm";

    public static final String FORMAT_8 = "yyyy/MM/dd";

    public static final String FORMAT_9 = "MM/dd";

    /**
     * 按格式获取对应时间的字符串
     *
     * @param [date, format]
     * @time: 2020/8/28 9:30
     * @author: Rock
     * @version 1.0
     */
    public static String dateToStr(Date date, String format) {
        if (date != null) {
            if (StringUtil.isBlank(format)) {
                format = FORMAT_1;
            }
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        }
        return "";
    }

    /**
     * @param [dateTime]
     * @time: 2020/9/9 11:53
     * @author: Rock
     * @version 1.0
     */
    public static Date strToDate(String dateTime) {
        if (StringUtils.isNotEmpty(dateTime)) {
            SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_4);
            try {
                return sdf.parse(dateTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static Date strToDate(String dateTime,  String format) {
        if (StringUtils.isNotEmpty(dateTime)) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try {
                return sdf.parse(dateTime);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 用户处理mongodb的时间问题
     *
     * @param type 1=获取时间加上当前时区与标准时区差；2=获取时间减去当前时区与标准时区差
     * @time: 2020/9/27 8:59
     * @author: Rock
     * @version 1.0
     */
    public static void hanldeMongoDate(Date date, int type) {
        int offset = TimeZone.getDefault().getRawOffset();
        if (type == 1) {
            date.setTime(date.getTime() + offset);
        } else if (type == 2) {
            date.setTime(date.getTime() - offset);
        }
    }

    /**
     * @param stamp
     * @param format
     * @time: 2020/10/21 10:23
     * @author: Rock
     * @version 1.0
     */
    public static String stampToDateStr(long stamp, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        Date date = new Date(stamp);
        return simpleDateFormat.format(date);
    }

    /**
     * 日期格式转换成 时间戳 (毫秒)
     * @param dateTime 日期字符串
     * @param format 日期格式
     * @time: 2021/3/4 18:05
     * @author: Rock
     * @version 1.0
     */
    public static long strToTimestamp(String dateTime, String format) {
        if (StringUtils.isNotEmpty(dateTime)) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            try {
                return sdf.parse(dateTime).getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    /**
     * @param time
     * @param format
     * @time: 2020/9/16 16:44
     * @author: Rock
     * @version 1.0
     */
    public static String timestampToStr(long time, String format) {
        if (time > 0) {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(new Date(time));
        }
        return null;
    }

    /**
     * @time: 2020/11/4 11:10
     * @author: Rock
     * @version 1.0
     */
    public static Double nowTimestampToDouble() {
        // 保留两位小数
        return Math.round((System.currentTimeMillis() / 1000.0) *100) /100.0;
    }

    /**
     * 当前时间戳 秒为单位
     * @time: 2020/11/4 11:10
     * @author: Rock
     * @version 1.0
     */
    public static Long nowTimestampToLong() {
        return System.currentTimeMillis() / 1000;
    }

    /**
     * 获取UTC时间
     *
     * @time: 2020/11/26 10:02
     * @author: Rock
     * @version 1.0
     */
    public static Date getUTCDate() {
        // 1、取得本地时间：
        Calendar cal = Calendar.getInstance();
        // 2、取得时间偏移量：
        int zoneOffset = cal.get(Calendar.ZONE_OFFSET);
        // 3、取得夏令时差：
        int dstOffset = cal.get(Calendar.DST_OFFSET);
        // 4、从本地时间里扣除这些差量，即可以取得UTC时间：
        cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        return cal.getTime();
    }

    /**
     * 给时间添加天数
     *
     * @param date
     * @param day
     * @time: 2020/11/26 10:15
     * @author: Rock
     * @version 1.0
     */
    public static Date addDay(Date date, int day) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DATE, day);
        return c.getTime();
    }


    /**
     * @description 解决时区问题
     * @author cwj
     * @param [date]
     * @return java.util.Date
     * @date @time 2024/12/26 9:28
     **/
    public static Date getDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.getTime();
    }

    /**
     * 获取星期几（1-7表示周一到周日）
     *
     * @param date
     * @time: 2020/12/18 15:02
     * @author: Rock
     * @version 1.0
     */
    public static int getWeekOfDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int day = cal.get(Calendar.DAY_OF_WEEK) - 1;
        return day <= 0 ? 7 : day;
    }

    /**
     * @time: 2021/1/13 14:49
     * @author: Rock
     * @version 1.0
     */
    public static int getHourAndMinute() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE);
    }

    /**
     * @param date
     * @param hour
     * @param minute
     * @time: 2021/2/3 10:22
     * @author: Rock
     * @version 1.0
     */
    public static Date setHourAndMinute(Date date, int hour, int minute) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当天零点的时间戳，单位/秒
     *
     * @time: 2021/5/28 10:38
     * @author: Rock
     * @version 1.0
     */
    public static long getTodayZeroTimestamp() {
        long nowTime = System.currentTimeMillis();
        long todayStartTime = nowTime - ((nowTime + TimeZone.getDefault().getRawOffset()) % (24 * 60 * 60 * 1000L));
        return todayStartTime / 1000;
    }

    /**
     * 判断videoId力截取的时间是否超过拨打视频的等待时间
     *
     * @param videoId
     * @time: 2021/1/15 9:20
     * @author: Rock
     * @version 1.0
     */
    public static boolean isTimeout(String videoId , int VIDEO_WAIT_TIME) {
        if (StringUtil.isNotBlank(videoId)) {
            long time = 0;
            if(videoId.contains("_")){
                String[] arr = videoId.split("_");
                time = Long.valueOf(arr[arr.length - 1]);
            }else{
                String[] arr = videoId.split("-");
                time = DateUtil.strToTimestamp(arr[arr.length - 1], DateUtil.FORMAT_6) / 1000;
            }


            return VIDEO_WAIT_TIME < System.currentTimeMillis() / 1000 - time;
        }
        return true;
    }

    /**
     * 系统有关数据过期时间的统一获取
     *
     * @time: 2021/2/4 14:47
     * @author: Rock
     * @version 1.0
     */
    public static Date getSystemExpiryAt() {
        //所有记录的失效时间天数 3个月
        return addDay(new Date(), Const.EXPIRY_TIME_DAY);
    }


    /**
     * @description 设置数据的过期时间，过期数据统一由TTL索引清楚
     * @author cwj
     * @param [addDay]
     * @return java.util.Date
     * @date @time 2025/6/20 9:18
     **/
    public static Date getSystemExpiryAt(int addDay) {
        //所有记录的失效时间天数 3个月
        return addDay(new Date(),addDay);
    }

    /**
     * 定位轨迹数据过期时间的 获取 (是7天后 23:59 失效)
     *
     * @time: 2021/11/23 19:47
     * @author: weichao
     * @version 1.0
     */
    public static Date getDevLocExpiryAt() {
        //获取今天的 23.59 的时间 然后加上间隔 时间
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            String formatDate = format.format(new Date());
            Calendar cal = Calendar.getInstance();
            cal.setTime(format.parse(formatDate));
            cal.add(Calendar.DAY_OF_YEAR,1);
            return addDay(new Date(cal.getTime().getTime()-1), Const.LOC_TIME_DAY);
        }catch (Exception e){
            //e.printStackTrace();
            System.out.println("e:"+e.getMessage());
            return null;
        }

    }


    /**
     * @param date
     * @time: 2021/3/9 9:37
     * @author: Rock
     * @version 1.0
     */
    public static boolean isDate(String date) {
        String regExp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(date);
        return m.matches();
    }

    /**
     * @description 获取系统当前Date时间
     * @author cwj
     * @param []
     * @return java.util.Date
     * @date @time 2024/12/25 17:42
     **/
    public static Date getCurrentDate(){
        LocalDateTime now = LocalDateTime.now();
        // 指定时区，将 LocalDateTime 转为 ZonedDateTime
        ZoneId zoneId = ZoneId.systemDefault(); // 使用系统默认时区
        ZonedDateTime zonedDateTime = now.atZone(zoneId);
        // 将 ZonedDateTime 转换为 Date
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * @description 将rfc3339格式的时间字符串转换指定格式的时间字符串
     * @author cwj
     * @param [rfc3339Time, format]
     * @return java.lang.String
     * @date @time 2025/1/4 16:42
     **/
    public static String rfc3339FormatDateStr(String rfc3339Time,String format) {
        // 解析 RFC3339 时间字符串为 ZonedDateTime 对象
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(rfc3339Time);

        // 定义目标格式的 DateTimeFormatter
        DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern(format);

        // 格式化 ZonedDateTime 为指定格式的字符串
        return  zonedDateTime.format(targetFormatter);
    }

    /**
     * @description 转换时间格式，解决时区偏移8个小时的问题
     * @author cwj
     * @param [dateString, format, isStartDate]
     * @return java.util.Date
     * @date @time 2025/2/12 9:51
     **/
    public static Date convertStrToDate(String dateString,String format, boolean isStartDate) throws Exception {
        // 设置时区为 Asia/Shanghai
        // 获取当前系统的默认时区
        TimeZone currentTimeZone = TimeZone.getDefault();

        // 获取当前时区的 ID（例如："Asia/Shanghai"）
        ZoneId zoneId = ZoneId.of(currentTimeZone.getID());
        //ZoneId zoneId = ZoneId.of("UTC");
        // 解析日期字符串，转换为 LocalDate
        LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern(format));

        // 转换为 ZonedDateTime 并设置时分秒为开始时间（00:00:00）或结束时间（23:59:59）
        ZonedDateTime zonedDateTime;
        if (isStartDate) {
            zonedDateTime = localDate.atStartOfDay(zoneId);  // 获取当天的开始时间
            zonedDateTime = zonedDateTime.minusHours(8);
        } else {
            //zonedDateTime = localDate.plusDays(1).atStartOfDay(zoneId).withZoneSameInstant(ZoneOffset.UTC);
            zonedDateTime = localDate.atTime(23-8, 59, 59, 999000000).atZone(zoneId);  // 获取当天的结束时间
        }
        // 将 ZonedDateTime 转换为 Date 对象
        return Date.from(zonedDateTime.toInstant());
    }


    /**
     * @description
     * @author cwj
     * @param [dateString, format, isStartDate]
     * @return java.lang.Long
     * @date @time 2025/5/6 15:27
     **/
    public static Long convertStrToTimeStamp(String dateString,String format, boolean isStartDate) throws Exception {
        // 设置时区为 Asia/Shanghai
        // 获取当前系统的默认时区
        TimeZone currentTimeZone = TimeZone.getDefault();

        // 获取当前时区的 ID（例如："Asia/Shanghai"）
        ZoneId zoneId = ZoneId.of(currentTimeZone.getID());
        //ZoneId zoneId = ZoneId.of("UTC");
        // 解析日期字符串，转换为 LocalDate
        LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern(format));

        // 转换为 ZonedDateTime 并设置时分秒为开始时间（00:00:00）或结束时间（23:59:59）
        ZonedDateTime zonedDateTime;
        if (isStartDate) {
            zonedDateTime = localDate.atStartOfDay(zoneId);  // 获取当天的开始时间
        } else {
            zonedDateTime = localDate.atTime(23, 59, 59, 999000000).atZone(zoneId);  // 获取当天的结束时间
        }
        // 将 ZonedDateTime 转换为 Date 对象
        return zonedDateTime.toInstant().toEpochMilli();
    }


    /**
     * @description 字符串时间转换
     * @author cwj
     * @param [dateString, format, isStartDate]
     * @return java.util.Date
     * @date @time 2025/5/6 13:59
     **/
    public static Date convertStrToDate2(String dateString,String format, boolean isStartDate) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        if(isStartDate) {
            dateString += " 00:00:00";
        }else {
            dateString += " 23:59:59";
        }
        return sdf.parse(dateString);
    }

    /*public static void main(String[] args) {

        System.out.println(String.format("double: "+nowTimestampToDouble()));
        System.out.println(String.format("long: "+nowTimestampToLong()));

        System.out.println(String.format("UTC时间: "+DateUtil.getUTCDate().getTime()/ 1000));

        Long time = DateUtil.strToTimestamp("20241018134000",FORMAT_2);
        String dateTimeStr = DateUtil.timestampToStr(time,FORMAT_1);
        String day = "20231118";
        Date date = DateUtil.strToDate(day, "yyyyMMdd");
        //获取星期  几（1-7表示周一到周日）
        int weekOfDate = DateUtil.getWeekOfDate(date);
        String startDate = DateUtil.dateToStr(DateUtil.addDay(date, 1-weekOfDate), "yyyyMMdd");
        startDate = startDate+"000000";
        String endDate = DateUtil.dateToStr(DateUtil.addDay(date, 7-weekOfDate), "yyyyMMdd");
        endDate = endDate+"235959";
        System.out.println(String.format("startDate:%s, endDate:%s ", startDate, endDate));
    }*/

    public static String numToMonthOrDayStr(Integer num){
        if(ObjectUtils.isEmpty(num)) {
            return "";
        }
        if(num<10){
            return  "0"+num;
        } else {
            return num.toString();
        }

    }

    /**
     * @param [startTime, vo]
     * @return com.iot08.common.entity.app.StartEndTime
     * @description 组装时间对象
     * @author cwj
     * @date @time 2025/3/28 15:51
     **/
    public static StartEndTime assembleStartEndTime(Integer deadlineYear, Integer deadlineMonth) throws ParseException {
        Date startTime = null;
        Date endTime;
        StartEndTime startEndTime = new StartEndTime();
        LocalDateTime localDateTime = LocalDateTime.now();
        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_1);
        if(org.springframework.util.ObjectUtils.isEmpty(deadlineYear) && org.springframework.util.ObjectUtils.isEmpty(deadlineMonth)) {
            endTime = new Date();
        } else if(!org.springframework.util.ObjectUtils.isEmpty(deadlineYear) && !org.springframework.util.ObjectUtils.isEmpty(deadlineMonth)) {
            //组装时间
            int lastDay = YearMonth.of(deadlineYear, deadlineMonth).lengthOfMonth();
            //组装字符串的月
            String month = numToMonthOrDayStr(deadlineMonth);
            if(deadlineYear.equals(localDateTime.getYear()) && deadlineMonth.equals(localDateTime.getDayOfMonth())) {
                endTime = new Date();
            } else {
                //组装字符串的天
                String day = numToMonthOrDayStr(lastDay);
                endTime = sdf.parse(deadlineYear+"-"+month+"-"+day+" 23:59:59");
            }
            startTime = sdf.parse(deadlineYear+"-"+month+"-01 00:00:00");
        } else if(!org.springframework.util.ObjectUtils.isEmpty(deadlineYear) && org.springframework.util.ObjectUtils.isEmpty(deadlineMonth)){
            if(deadlineYear>=localDateTime.getYear()){
                endTime = new Date();
                startTime = sdf.parse(localDateTime.getYear() + "-01-01 00:00:00");
            } else {
                endTime = sdf.parse(deadlineYear+"-12-31 23:59:59");
                startTime = sdf.parse(deadlineYear + "-01-01 00:00:00");
            }
        } else {
            String month = numToMonthOrDayStr(deadlineMonth);
            if(deadlineMonth>=localDateTime.getDayOfMonth()) {
                endTime = new Date();
            } else {
                int lastDay = YearMonth.of(localDateTime.getYear(), deadlineMonth).lengthOfMonth();
                //组装字符串的天
                String day = numToMonthOrDayStr(lastDay);
                endTime = sdf.parse(localDateTime.getYear()+"-"+month+"-"+day+"23:59:59");
            }
            startTime = sdf.parse(LocalDateTime.now().getYear()+"-"+deadlineMonth+"-01 00:00:00");
        }
        startEndTime.setStartTime(startTime);
        startEndTime.setEndTime(endTime);
        return startEndTime;
    }

    public static void main(String[] args) {
        // 示例 RFC3339 时间字符串
      /*  String rfc3339Time = "2025-01-04T15:30:00+08:00";

        String formattedTime = rfc3339FormatDateStr(rfc3339Time,FORMAT_2);
*/
        String startTime = "2025-02-03";
        String endTime = "2025-02-11";
        try {
            Date sTime = convertStrToDate(startTime,FORMAT_4,true); // 打印结果
            Date eTime = convertStrToDate(endTime,FORMAT_4,false); // 打印结果
            System.out.println("转换后的时间字符串: " + sTime+","+eTime);
        } catch (Exception e){
            e.printStackTrace();
        }
    }


}
